﻿#pragma once
#include "SimpleDSP.h"
#include "lang/Math.h"
#include <cmath>
namespace yzrilyzr_dsp{
	EBCLASS(RingBufferUtil){
	public:
	static inline u_index mod(u_index x, u_index m){
		if(m == 0)return 0;
		u_index y=x % static_cast<u_index>(m);
		return  (y < 0)?y + m:y;
	}
	static inline u_sample mod1(u_sample x){
		return x - ((u_index)x);
	}
	/**
	*	反馈系数修正(根据RingBuffer频率(length=sampleRate/freq-1))
	*/
	static inline u_sample feedbackCoeff(u_sample feedback, u_sample freq){
		return pow(pow(abs(feedback), static_cast<u_sample>(6.0)), static_cast<u_sample>(1.0) / freq) * static_cast<u_sample>(signbit(feedback)?-1.0:1.0);
	}
	/**
	* 根据时间(ms)和采样率获取延迟线长度
	*/
	static inline u_sample ms2DelayIndex(u_time_ms delayTimeMs, u_sample sampleRate){
		return static_cast<u_sample>(delayTimeMs) * sampleRate / static_cast<u_sample>(1000.0);
	}
	/**
	* 根据频率和采样率获取延迟线长度
	*/
	static inline u_sample freq2delayIndex(u_freq freq, u_sample sampleRate){
		return sampleRate / freq - static_cast<u_sample>(1.0);
	}
	};
	template<typename T>
	EBCLASS(RingBuffer){
	protected:
	u_index _length;
	u_index _pointer;//指示最旧数据
	public:
	T * buffer=nullptr;
	RingBuffer() : _length(0), _pointer(0), buffer(nullptr){}
	RingBuffer(u_index size) : _length(size), _pointer(0), buffer(nullptr){
		if(size > 0){  // 仅当 size>0 时才分配内存
			buffer=new T[size];
			std::fill(buffer, buffer + _length, T());
		}
	}
	~RingBuffer(){
		delete[] buffer;
	}
	/**
	 * 向最旧写入一个数据，并移动至下一个最旧位置
	 * 上一个最旧变成最新
	 */
	inline void write(T d){
		buffer[_pointer]=d;
		_pointer+=1;
		if(_pointer >= _length) _pointer=0;
	}
	inline void reset(){
		_pointer=0;
	}
	/**
	 * 获取最旧（延迟线末尾）
	 */
	inline T oldest() const{
		return buffer[_pointer];
	}
	inline u_index pointer() const{
		return _pointer;
	}
	inline T get(u_index pointer) const{
		return buffer[pointer];
	}
	inline u_index capacity() const{
		return _length;
	}
	void ensureCapacity(u_sample delayIndex){
		ensureCapacity(static_cast<u_index>(delayIndex + 10));
	}
	void ensureCapacity(u_index required){
		if(required > _length){
			u_index newLength=yzrilyzr_lang::Math::max(static_cast<u_index>(1.5 * _length), required);
			T * newBuffer=new T[newLength];
			u_index copyLen=_length - _pointer;
			if(copyLen > 0){
				std::copy(buffer + _pointer, buffer + _length, newBuffer);
				std::copy(buffer, buffer + _pointer, newBuffer + copyLen);
			}
			std::fill(newBuffer + _length, newBuffer + newLength, T());
			delete[] buffer;
			buffer=newBuffer;
			_pointer=0;
			_length=newLength;
		}
	}
	/**
	 * @param index 0:最旧，length-1:最新
	 */
	inline T getFromOldest(u_index index) const{
		return buffer[RingBufferUtil::mod(index + _pointer, _length)];
	}
	/**
	 * 全填充
	 */
	inline void fill(T v) const{
		std::fill(buffer, buffer + _length, v);
	}
	/**
	 * 填充
	 */
	void write(T * src, u_index offsetInBuffer, u_index offsetInSrc, u_index length);
	/**
	 * 复制buffer到dst中
	 */
	void copyTo(T * dst, u_index offsetInBuffer, u_index offsetInDst, u_index length);
	/**
	 * @param index 0:最新，length-1:最旧
	 */
	inline T getFromNewest(u_index index) const{
		return buffer[RingBufferUtil::mod(_pointer - 1 - index, _length)];
	}
	inline T nextNewest(){
		T n=newest();
		if(++_pointer >= _length) _pointer=0;
		return n;
	}
	/**
	 * 获取最新
	 */
	inline T newest() const{
		return buffer[RingBufferUtil::mod(_pointer - 1, _length)];
	}
	};
	typedef RingBuffer<u_sample> RingBufferSample;
}
